﻿using System;
using System.IO;
using System.IO.IsolatedStorage;
using System.Runtime.Serialization;
using Prometheus.UIUtility.Storage;

namespace DeepMixWorkflow
{
    public class StorageFile<T> : StorageProperty<T>
    {
        private readonly string _fileName;

        public StorageFile(string fileName, Func<T> lazyLoad)
            : base(fileName, true, lazyLoad)
        {
            _fileName = fileName;
        }

        public string FileName
        {
            get { return _fileName; }
        }

        protected override bool IsPropertyExists(string name)
        {
            return IsolatedStorageHelper.Do(storage => storage.FileExists(name));
        }

        public void DoReadFromBegin(Action<Stream> action)
        {
            DoRead<object>(stream =>
                {
                    action(stream);
                    return null;
                });
        }

        public void DoWriteNew(Action<Stream> action)
        {
            DoWrite<object>(stream =>
                {
                    action(stream);
                    return null;
                });
        }

        private TRet DoWrite<TRet>(Func<Stream, TRet> writeAction)
        {
            return IsolatedStorageHelper.Do(file =>
                {
                    using (
                        IsolatedStorageFileStream stream = file.OpenFile(_fileName, FileMode.Create, FileAccess.Write))
                    {
                        return writeAction(stream);
                    }
                });
        }

        private TRet DoRead<TRet>(Func<Stream, TRet> readAction)
        {
            return IsolatedStorageHelper.Do(file =>
                {
                    using (IsolatedStorageFileStream stream = file.OpenFile(_fileName, FileMode.Open))
                    {
                        return readAction(stream);
                    }
                });
        }

        protected override T GetValue(string name)
        {
            return IsolatedStorageHelper.Do(file => DoRead(stream =>
                {
                    var serializer = new DataContractSerializer(typeof (T));
                    object result = serializer.ReadObject(stream);
                    return (T) result;
                }));
        }

        protected override void SetValue(string name, T value)
        {
            IsolatedStorageHelper.Do(file => DoWrite<object>(stream1 =>
                {
                    var serializer = new DataContractSerializer(typeof (T));
                    serializer.WriteObject(stream1, value);
                    return null;
                }));
        }
    }

    internal static class IsolatedStorageHelper
    {
        public static TRet Do<TRet>(Func<IsolatedStorageFile, TRet> func)
        {
            using (IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                return func(storage);
            }
        }
    }
}